﻿using AutoMapper;
using B.S.BaseData.Api.Read.Command.RBAC;
using B.S.BaseData.ErrorCode;
using B.S.BaseData.Infrastructure.Interface;
using B.S.BataBase.Domain.DTO;
using B.S.BataBase.Domain.DTO.Token;
using B.S.BataBase.Domain.RBAC;
using MediatR;
using Microsoft.IdentityModel.Tokens;
using Newtonsoft.Json;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;

namespace B.S.BaseData.Api.Read.CommandHandler.RBAC
{
    public class LoginCommandHandler : IRequestHandler<LoginCommand, APIResult<LoginDTO>>
    {
        private readonly IBaseRepository<UserModel> _userrepository;
        private readonly IBaseRepository<UserRoleModel> _userroleRepository;
        private readonly IBaseRepository<RoleModel> _roleroleRepository;
        private readonly IMapper _mapper;
        private readonly IHttpContextAccessor _contextAccessor;
        private readonly IConfiguration _config;
        public LoginCommandHandler(IBaseRepository<UserModel> userrepository,
            IBaseRepository<UserRoleModel> userroleRepository,
            IMapper mapper,
            IBaseRepository<RoleModel> roleroleRepository,
            IConfiguration config,
            IHttpContextAccessor contextAccessor)
        {
            _userrepository = userrepository;
            _userroleRepository = userroleRepository;
            _mapper = mapper;
            _roleroleRepository = roleroleRepository;
            _config = config;
            _contextAccessor = contextAccessor;
        }
        public async Task<APIResult<LoginDTO>> Handle(LoginCommand request, CancellationToken cancellationToken)
        {
            APIResult<LoginDTO> result=new APIResult<LoginDTO>();
            var list =await _userrepository.GetValues(x=>x.UserName==request.userName);
            if (list == null)
            {
                result.Code = ApiEnum.Fail;
                result.Msg = "用户名不存在";
                return await Task.FromResult(result);
            }
            if (list.UserPwd != request.userPwd)
            {
                result.Code = ApiEnum.Fail;
                result.Msg = "密码不匹配";
                return await Task.FromResult(result);
            }
            LoginDTO dTO=new LoginDTO();

            var data= _userroleRepository.GetAll().Where(x=>x.UserId==list.Id).Select(x=>x.RoleId).ToList();
            dTO.RoleId = data;
            dTO.RoleName =await GetRoleName(data);
            dTO.UserName=request.userName;
            result.Code = ApiEnum.Success;
            result.Msg = "登录成功";
            result.Data = dTO;
            result.Token = CreateTokenString(list.Id,list.UserName, dTO.RoleName);
            return await Task.FromResult(result);
        }

        /// <summary>
        /// 根据角色id集合获取id名称
        /// </summary>
        /// <param name="ids"></param>
        /// <returns></returns>
        public async Task<string> GetRoleName(List<long> ids)
        {
            string s = "";
            foreach (var id in ids)
            {
                s += (await _roleroleRepository.GetValues(x => x.Id == id)).RoleName + ",";
            }
            return s.TrimEnd(',');
        }
        /// <summary>/// 生成 JWT Token（令牌）/// </summary>/// <returns></returns>
        private TokenResponse CreateTokenString(long id,string loginname, string rolename)
        {
            //配置JWT
            var jwtSettings = _config.GetSection("JwtSettings").Get<JwtSettings>()!;
            //私钥
            var secretByte = Encoding.UTF8.GetBytes(jwtSettings.SigningKey);
            // 非对称加密
            var signingKey = new SymmetricSecurityKey(secretByte);
            // 使用256 生成数字签名
            var signingCredentials = new SigningCredentials(signingKey, SecurityAlgorithms.HmacSha256);

            var claims = new[]
            {
                new Claim("UserId",id.ToString()),
                new Claim("UserName",loginname),
                new Claim("RoleName",rolename),
            };


            // 生成Token
            var token = new JwtSecurityToken(
                issuer: jwtSettings.Issuer,
                audience: jwtSettings.Audience,
                expires: DateTime.Now.AddMinutes(jwtSettings.TokenExpires), // 一天后过期
                signingCredentials: signingCredentials,
                claims: claims
            );
            // 生成token 字符串
            var strToken = new JwtSecurityTokenHandler().WriteToken(token);

            var refreshToken = new Refreshtoken
            { 
                Token=Guid.NewGuid().ToString("N"),
                Expires=DateTime.UtcNow.AddDays(jwtSettings.RefreshTokenExpirationDays),
                CreateTime = DateTime.UtcNow,
                UserId= id
            };
            

            return new TokenResponse
            { 
                AccessToken= strToken,
                RefreshToken=JsonConvert.SerializeObject(refreshToken)
            };
        }
    }
}
